import pandas as pd
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import re
import tkinter as tk
from tkinter import filedialog

# 关闭 tkinter 主窗口
root = tk.Tk()
root.withdraw()

# 让用户选择 Excel 文件
file_path = filedialog.askopenfilename(title='请选择 Excel 文件', filetypes=[('Excel files', '*.xlsx *.xls')])

# 如果用户取消选择
if not file_path:
    print("未选择文件，程序退出。")
    exit()

# 读取 Excel 文件
df = pd.read_excel(file_path)

# 确保包含所需列
required_cols = ['文件名称', '节点P平均偏差', '节点P偏差最大值']
for col in required_cols:
    if col not in df.columns:
        raise ValueError(f"缺少列：{col}")

# 提取时间标签（如 20231203_1450）
df['时间标签'] = df['文件名称'].apply(
    lambda x: re.search(r'(\d{8}_\d{4})', str(x)).group(1) if re.search(r'(\d{8}_\d{4})', str(x)) else '未知'
)

# 分组：计算平均值 + 统计数量
grouped = df.groupby('时间标签').agg({
    '节点P平均偏差': 'mean',
    '节点P偏差最大值': 'mean',
    '文件名称': 'count'
}).rename(columns={'文件名称': '样本数量'}).reset_index()

# 排序
grouped = grouped.sort_values(by='时间标签')

# # ✅ matplotlib 双轴可视化
# fig, ax1 = plt.subplots(figsize=(10, 6))

# # 第一Y轴：偏差曲线
# color1 = 'tab:blue'
# ax1.set_xlabel('时间标签')
# ax1.set_ylabel('偏差值', color=color1)
# ax1.plot(grouped['时间标签'], grouped['节点P平均偏差'], marker='o', label='节点P平均偏差', color='blue')
# ax1.plot(grouped['时间标签'], grouped['节点P偏差最大值'], marker='s', label='节点P偏差最大值', color='green')
# ax1.tick_params(axis='y', labelcolor=color1)
# ax1.set_xticklabels(grouped['时间标签'], rotation=45)
# ax1.grid(True)

# # 图例
# ax1.legend(loc='upper left')

# # 第二Y轴：样本数量
# ax2 = ax1.twinx()
# color2 = 'tab:red'
# ax2.set_ylabel('样本数量', color=color2)
# ax2.bar(grouped['时间标签'], grouped['样本数量'], alpha=0.3, color='red', label='样本数量')
# ax2.tick_params(axis='y', labelcolor=color2)

# # 保存并显示
# plt.title('不同类别下的节点P偏差与样本数量统计')
# plt.tight_layout()
# plt.savefig('偏差与数量统计.png')
# plt.show()

# ✅ Plotly 可视化（交互式双轴）
fig2 = go.Figure()

# 折线图（偏差）
fig2.add_trace(go.Scatter(x=grouped['时间标签'], y=grouped['节点P平均偏差'],
                          mode='lines+markers', name='节点P平均偏差', yaxis='y1'))
fig2.add_trace(go.Scatter(x=grouped['时间标签'], y=grouped['节点P偏差最大值'],
                          mode='lines+markers', name='节点P偏差最大值', yaxis='y1'))

# 柱状图（样本数量）
fig2.add_trace(go.Bar(x=grouped['时间标签'], y=grouped['样本数量'],
                      name='样本数量', yaxis='y2', opacity=0.4, marker_color='red'))

# 配置双轴
fig2.update_layout(
    title='不同类别下的节点P偏差与样本数量统计（交互式）',
    xaxis=dict(title='时间标签'),
    yaxis=dict(title='偏差值', side='left'),
    yaxis2=dict(title='样本数量', overlaying='y', side='right'),
    legend=dict(x=0.01, y=0.99),
    margin=dict(l=60, r=60, t=60, b=60)
)

# 保存交互式图
fig2.write_html('偏差与数量统计.html')
fig2.show()
# ==== 新增：计算样本数量平均值 ====
average_count = grouped['样本数量'].mean()
print(f"\n样本数量平均值：{average_count:.2f}")

# 找出样本数量低于平均值的时间标签
low_sample_tags = grouped[grouped['样本数量'] < average_count]['时间标签'].tolist()

# 根据这些标签筛选对应文件名称
low_sample_files = df[df['时间标签'].isin(low_sample_tags)]['文件名称'].tolist()

# 保存到 TXT 文件
output_mv_file = '低于平均数量的文件移动命令.txt'
with open(output_mv_file, 'w', encoding='utf-8') as f:
    for name in low_sample_files:
        f.write(f"mv {name} ../bak\n")

print(f"mv 命令已保存至：{output_mv_file}")